package com.atgion.manager.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.atgion.manager.mapper.SysRoleMapper;
import com.atgion.manager.service.SysRolePermissionService;
import com.atgion.manager.service.SysRoleResourceService;
import com.atgion.manager.service.SysRoleService;
import com.atgion.spzx.model.bo.system.SysRolePermissionBO;
import com.atgion.spzx.model.dto.system.SysRolePermissionUpdateDTO;
import com.atgion.spzx.model.entity.system.SysRole;
import com.atgion.spzx.model.entity.system.SysRolePermission;
import com.atgion.spzx.model.vo.base.Result;
import com.atgion.spzx.model.vo.system.SysRoleVO;
import com.atgion.manager.util.CglibUtil;
import com.atgion.manager.util.CollectionUtil;
import com.atgion.manager.util.JwtTokenUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.google.common.collect.Sets;
import com.atgion.exception.enums.DelStatusEnums;
import com.atgion.exception.enums.StatusEnums;
import com.atgion.exception.exception.GlobalException;
import com.atgion.exception.exception.GlobalExceptionEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>
        implements SysRoleService {

    final JwtTokenUtil jwtTokenUtil;

    final SysRoleResourceService sysRoleResourceService;

    @Autowired
    SysRolePermissionService sysRolePermissionService;

    @Autowired
    SysPermissionServiceImpl sysPermissionService;
    @Override
    public IPage<SysRole> getPage(Map<String, Object> params) {
        int pageSize = Integer.parseInt(String.valueOf(params.get("size")));
        int pageNum = Integer.parseInt(String.valueOf(params.get("current")));
        LambdaQueryWrapper<SysRole> wrapper = createWrapper(params);

        return page(new Page<>(pageNum, pageSize), wrapper);
    }

    private LambdaQueryWrapper<SysRole> createWrapper(Map<String, Object> params) {
        String roleName = (String) params.get("roleName");
        String roleCode = (String) params.get("roleCode");
        String status = (String) params.get("status");

        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotEmpty(roleName), SysRole::getRoleName, roleName);
        wrapper.like(StrUtil.isNotEmpty(roleCode), SysRole::getRoleCode, roleCode);
        wrapper.eq(StrUtil.isNotEmpty(status), SysRole::getStatus, status);
        wrapper.eq( SysRole::getIsDeleted, DelStatusEnums.DISABLE.getCode());

        return wrapper;
    }

    @Override
    public Result<List<SysRoleVO>> getAllRoles(String authorizationHeader) {
        if (authorizationHeader == null || !authorizationHeader.startsWith(jwtTokenUtil.getTokenHead())) {
            throw new GlobalException(GlobalExceptionEnum.ERROR_UNAUTHORIZED.getMessage());
        }

        List<SysRoleVO> sysRoleVOS = new ArrayList<>();

        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getStatus, StatusEnums.ENABLE.getCode());

        List<SysRole> list = list(wrapper);
        if (!list.isEmpty()) {
            for (SysRole sysRole : list) {
                SysRoleVO sysRoleVO = new SysRoleVO();
                sysRoleVO.setRoleName(sysRole.getRoleName());
                sysRoleVO.setRoleCode(sysRole.getRoleCode());
                sysRoleVO.setRoleDesc(sysRole.getRoleDesc());
                sysRoleVOS.add(sysRoleVO);
            }
            return Result.success(sysRoleVOS);
        }
        return Result.success();
    }

    @Override
    public List<String> getUserRole(Long id) {
        return baseMapper.getUserRole(id);
    }

    @Override
    public List<SysRole> queryRoleListByRoleCode(List<String> roleCode) {

        LambdaQueryWrapper<SysRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(SysRole::getRoleCode, roleCode);
        lambdaQueryWrapper.eq(SysRole::getStatus,StatusEnums.ENABLE.getCode());

        return list(lambdaQueryWrapper);
    }

    @Override
    public Result<Boolean> add(SysRole sysRole) {

        if (sysRole.getId() != null) {
            log.info("修改角色对象入参: {}", JSONUtil.parse(sysRole));
            return Result.success(updateById(sysRole));
        } else {
            sysRole.setStatus(StatusEnums.ENABLE.getCode());
            sysRole.setIsDeleted(DelStatusEnums.DISABLE.getCode());
            sysRole.setType(1);
            log.info("添加角色对象入参: {}", JSONUtil.parse(sysRole));

            save(sysRole);

            LambdaQueryWrapper<SysRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(SysRole::getRoleCode, sysRole.getRoleCode());
            lambdaQueryWrapper.eq(SysRole::getIsDeleted, DelStatusEnums.DISABLE.getCode());

            SysRole sysRole1 = getOne(lambdaQueryWrapper);


            // 给角色绑定基础资源权限
            sysRoleResourceService.bindingRoleBasicResource(sysRole1.getId(), new ArrayList<>(Collections.singletonList(1L)));

            return Result.success();
        }
    }



    @Override
    public Result<List<Long>> getRoleResourceId(Long roleId) {

        return sysRoleResourceService.getRoleResourceId(roleId);
    }

    @Override
    public Result<Boolean> updateRoleResourceInfo(Long roleId, List<Long> resourceId) {
        log.info("修改角色资源信息入参: 角色ID: {} , 资源ID: {}", roleId, JSONUtil.parse(resourceId));

        sysRoleResourceService.deleteDataByRoleId(roleId);

        sysRoleResourceService.bindingRoleBasicResource(roleId, resourceId);

        return Result.success();
    }

    /*
    * 获取权限list
    * */
    @Override
    public List<Long> queryPermissionIdsWithRoleId(Long roleId) {
        LambdaQueryWrapper<SysRolePermission> queryWrapper = new LambdaQueryWrapper<SysRolePermission>()
                .eq(SysRolePermission::getRoleId, roleId);
        List<SysRolePermission> sysRolePermissions = sysRolePermissionService.list(queryWrapper);
        return sysRolePermissions.stream().map(SysRolePermission::getPermissionId).toList();
    }


    @Override
    public Boolean updatePermission(SysRolePermissionUpdateDTO sysRolePermissionUpdateDTO) {
        SysRolePermissionBO sysRolePermissionBO = CglibUtil.convertObj(sysRolePermissionUpdateDTO, SysRolePermissionBO::new);
        return sysRolePermissionService.updateById(sysRolePermissionBO);
    }

    @Override
    public boolean addPermissionForRoleId(Long roleId, List<Long> permissionIds) {
        // 查找原有权限
        LambdaQueryWrapper<SysRolePermission> queryWrapper = new LambdaQueryWrapper<SysRolePermission>()
                .eq(SysRolePermission::getRoleId, roleId);
        List<SysRolePermission> originRolePermissionList = sysRolePermissionService.list(queryWrapper);

        // 提取权限ID，并进行比较是否相同
        Set<Long> originPermissionSet = originRolePermissionList.stream()
                .map(SysRolePermission::getPermissionId).collect(Collectors.toSet());
        // 前端传输权限Ids，转换为 Set
        Set<Long> newPermissionSet = Sets.newHashSet(permissionIds);
        // 处理结果
        AtomicBoolean saveBath = new AtomicBoolean(true);
        CollectionUtil.handleDifference(
                originPermissionSet,
                newPermissionSet,
                // 处理增加和删除的权限
                (addPermissionSet, removePermissionSet) -> {
                    // 如有删除，则进行删除数据
                    if (!CollectionUtils.isEmpty(removePermissionSet)) {
                        LambdaQueryWrapper<SysRolePermission> removeQueryWrapper = new LambdaQueryWrapper<SysRolePermission>()
                                .eq(SysRolePermission::getRoleId, roleId)
                                .in(SysRolePermission::getPermissionId, removePermissionSet);
                        sysRolePermissionService.remove(removeQueryWrapper);
                    }
                    // 如有新增，则进行新增数据
                    if (!CollectionUtils.isEmpty(addPermissionSet)) {
                        List<SysRolePermission> addRolePermissionList = addPermissionSet.stream()
                                .map(permissionId -> new SysRolePermission(roleId, permissionId)).toList();
                        // 进行新增数据
                        saveBath.set(Db.saveBatch(addRolePermissionList));
                    }
                    // 保存角色权限到缓存
//                    sysPermissionService.saveRolePermissionToCache(roleId, permissionIds);
                }
        );
        return saveBath.get();
    }

}
